﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using WAF.Data;

namespace EntityTools.Logic.Interface
{
    class SqliteDbInfo : IDatabaseInfo
    {
        public List<string> GetTablesFromDb(string dbName)
        {
            List<string> tables = new List<string>();

            DbAccess.DbType = DbAccess.DatabaseType.SQLITE;
            DbAccess.ConnectionString = "Data Source=" + dbName;

            //获取表
            string tableSQL = "select name from sqlite_master where type='table' order by name";
            DataTable tb = DbAccess.ExeDataSet(tableSQL).Tables[0];

            foreach (DataRow row in tb.Rows)
            {
                tables.Add(row[0].ToString());
            }

            return tables;
        }

        public List<DbFieldInfo> GetFieldsFromTable(string tableName)
        {
            List<DbFieldInfo> fieldInfos = new List<DbFieldInfo>();
            string sharptype, dbtype, fieldSize, isUnique, isNotNull, isForeignKey, relTable, relIdField, relNameField;
            string tbSchema = DbAccess.ExeScalar("select sql from sqlite_master where type='table' and name='" + tableName + "'").ToString();

            int startIndex = tbSchema.IndexOf('(');
            int endIndex   = tbSchema.LastIndexOf(')');
            string[] fieldSql = tbSchema.Substring(startIndex + 1, endIndex - startIndex - 1).Split(',');

            DataTable tb = DbAccess.ExeDataSet("pragma table_info(" + tableName + ")").Tables[0];

            int i = 0;

            //rowid字段信息
            DbFieldInfo fInfo = new DbFieldInfo();
            fInfo.Name = "rowid";
            fInfo.FieldType = "long";
            fInfo.Sequence = (i++).ToString();
            fInfo.IsPrimeKey = "true";
            fInfo.IsUnique = "true";
            fInfo.IsNotNull = "true";
            fInfo.IsForeignKey = "false";
            fInfo.DatabaseType = "DbType.Int64";
            fInfo.Size = "0";
            fInfo.Description = "id";
            fInfo.RelTable = "";
            fInfo.RelIdField = "";
            fInfo.RelNameField = "";
            fieldInfos.Add(fInfo);

            foreach (DataRow row in tb.Rows)
            {
                //获取字段信息
                string fieldName = row["name"].ToString().Trim();
                getDbTypeString(row["type"].ToString().Trim(), out sharptype, out dbtype);
                getFieldAttribute(fieldSql, fieldName, out fieldSize, out isUnique, out isNotNull, out isForeignKey, out relTable, out relIdField, out relNameField);

                fInfo = new DbFieldInfo();

                fInfo.Name = fieldName;
                fInfo.FieldType = sharptype;
                fInfo.Sequence = (i++).ToString();
                fInfo.IsPrimeKey = "false";
                fInfo.IsUnique = isUnique;
                fInfo.IsNotNull = isNotNull;
                fInfo.IsForeignKey = isForeignKey;
                fInfo.DatabaseType = dbtype;
                fInfo.Size = fieldSize;
                fInfo.Description = getDescription(tableName, fieldName);
                fInfo.RelTable = relTable;
                fInfo.RelIdField = relIdField;
                fInfo.RelNameField = relNameField;

                fieldInfos.Add(fInfo);
            }

            return fieldInfos;
        }

        //获取字段类型
        private void getDbTypeString(string sqlitetype, out string sharptype, out string dbtype)
        {
            sharptype = "";
            dbtype = "";

            switch (sqlitetype.ToUpper())
            {
                case "INT":
                    sharptype = "int";
                    dbtype = "DbType.Int32";
                    break;
                case "INTEGER":
                    sharptype = "long";
                    dbtype = "DbType.Int64";
                    break;
                case "FLOAT":
                    sharptype = "float";
                    dbtype = "DbType.Double";
                    break;
                case "DOUBLE":
                    sharptype = "double";
                    dbtype = "DbType.Double";
                    break;
                case "TEXT":
                    sharptype = "string";
                    dbtype = "DbType.String";
                    break;
                default:
                    sharptype = "string";
                    dbtype = "DbType.String";
                    break;
            }
        }

        //获取字段属性
        private void getFieldAttribute(string[] fieldSql, string fieldName, out string fieldSize, out string isUnique, out string isNotNull, out string isForeignKey, out string relTable, out string relIdField, out string relNameField)
        {
            fieldSize = "0";
            isUnique = "false";
            isNotNull = "false";
            isForeignKey = "false";
            relTable = "";
            relIdField = "";
            relNameField = "";

            foreach (string ss in fieldSql)
            {
                string s = ss.Trim();

                //只能是开头的字段名匹配
                if (s.Trim().IndexOf(fieldName) == 1)
                {
                    //是否唯一
                    if (s.IndexOf(" UNIQUE") != -1) isUnique = "true";

                    //是否非空
                    if (s.IndexOf(" NOT NULL") != -1) isNotNull = "true";

                    //字符型字段长度
                    if (s.IndexOf(" CHAR(1)") != -1)
                        fieldSize = "1";
                    else if (s.IndexOf(" TEXT(") != -1)
                    {
                        int sIndex = s.IndexOf('(');
                        int eIndex = s.IndexOf(')');
                        fieldSize = s.Substring(sIndex + 1, eIndex - sIndex - 1);
                    }

                    //是否外键
                    if (s.IndexOf(" REFERENCES ") != -1)
                    {
                        string pattern = @"(\[\w+\])+";
                        MatchCollection matchs = Regex.Matches(s, pattern);

                        isForeignKey = "true";
                        relTable = matchs[2].Value.Replace("[", "").Replace("]", "");
                        relIdField = matchs[3].Value.Replace("[", "").Replace("]", "");
                        relNameField = matchs[1].Value.Replace("[", "").Replace("]", "");
                    }
                }
            }
        }

        //获取字段原有的描述信息
        private string getDescription(string className, string fieldName)
        {
            //如果没有原有实体类文件则跳过搜索
            //if (MainForm.bakFile == "") return "";

            //读取原有实体类文件的拷贝文件以获取描述信息
            StreamReader sr = null; // new StreamReader(MainForm.bakFile, Encoding.Default);

            string description = "";
            string preLine = "";

            //是否是该类的成员
            bool isThisClass = false;

            while (!sr.EndOfStream)
            {
                string line = sr.ReadLine();

                if (line.IndexOf("class " + className) > 0)
                {
                    isThisClass = true;
                }
                else if (isThisClass && line.IndexOf(" " + fieldName + " ") > 0 && preLine.IndexOf('"') > 0)
                {
                    int startIndex = preLine.IndexOf('"');
                    int endIndex = preLine.Remove(startIndex, 1).IndexOf('"');

                    description = preLine.Substring(startIndex+1, endIndex - startIndex);
                    break;
                }
                else
                {
                    preLine = line;
                }
            }

            sr.Close();
            return description == "" ? "" : description;
        }
    }
}
